const sequelize = require('sequelize')
// import { shop } from '../models/index'
const { shop, shopAuth, kind, good, translation } = require('../models/index')
const authController = require('./authController')
const tokenController = require('./tokenController')
const errorHelper = require('../util/errorHelper')
const uuidv5 = require('uuid/v5')
const bcrypt = require('bcrypt')
const tokenGenerator = require('../util/tokenGenerator')
const _ = require('lodash')

class ShopController {
  constructor() {
    this.saltSounds = 10
  }
  async createShop({ email, password, avatar }) {
    // 先检查是否已有该用户
    const checkAuth = await authController.isAuthExist({
      where: {
        idType: 'shop',
        identityType: 'email',
        identifier: email
      }
    })
    if (checkAuth.length) {
      throw errorHelper(400, 'account duplicate')
    }
    // 根据邮箱生成shopId
    const shopId = `shop-${uuidv5(email, uuidv5.URL)}`
    // 创建shop
    const newShop = await shop.create({ shopId, avatar })
    if (!newShop) {
      throw errorHelper(400, 'account duplicate')
    }
    // 通过用户提交的密码生成身份验证字符串
    const salt = bcrypt.genSaltSync(this.saltSounds)
    const credential = bcrypt.hashSync(password, salt)
    const newAuth = await authController.createAuth({
      idType: 'shop',
      uuId: shopId,
      identityType: 'email',
      identifier: email,
      credential
    })
    if (!newAuth) {
      throw errorHelper(400, 'account duplicate')
    }
    return shopId
  }

  async login({ identityType, identifier, password, loginTime, outdateTime, device, ip }) {
    // 先对比password和auth表中对应的密码，然后存储token表记录
    const checkAuth = await authController.isAuthExist({
      where: {
        idType: 'shop',
        identityType,
        identifier
      }
      // include: [{ model: shop, as: 'shop' }]
    })
    const targetAuth = checkAuth[0]
    if (!bcrypt.compareSync(password, targetAuth.credential)) {
      throw errorHelper(400, 'account or password error')
    }
    // if (!targetAuth) {
    //   throw errorHelper(400, 'account or password error')
    // }
    // if (!bcrypt.compareSync(password, targetAuth.credential)) {
    //   throw errorHelper(400, 'account or password error')
    // }
    const loginToken = tokenGenerator.generate(identifier, 10)
    const token = await tokenController.createToken({
      idType: 'shop',
      uuId: targetAuth.uuId,
      identityType,
      loginToken,
      loginTime,
      outdateTime,
      device,
      ip
    })
    const shopDetail = await this.getDetailByShopId(targetAuth.uuId)
    return { shopDetail, token: token.token }
  }

  async getDetailByShopId(shopId, isTokenValid) {
    const shopDetail = await shop.findOne({
      where: {
        shopId
      },
      include: isTokenValid ? [{ model: shopAuth, as: 'auths', attributes: ['identityType', 'identifier'] }] : []
    })
    if (!shopDetail.shopId) {
      throw errorHelper(400, 'shop not exist')
    }
    return shopDetail
  }

  async saveInfo(shopInfo) {
    const result = await shop.update(shopInfo, { where: { shopId: shopInfo.shopId } })
    if (!result) {
      throw errorHelper(400, 'field error')
    }
    return result
  }

  async addClickRate(shopId) {
    const result = await shop.update({ clickRate: sequelize.literal('`clickRate`+1') }, { where: { shopId } })
    if (result[0] !== 1) {
      throw errorHelper(500, 'server error')
    }
    return true
  }

  async getHotShops() {
    const hotShops = await shop.findAll({
      limit: 4,
      attributes: ['shopId', 'avatar', 'name'],
      order: [['clickRate', 'DESC']]
    })
    return hotShops
  }

  async search(keyWords) {
    const orParam = []
    _.forEach(keyWords, (item) => {
      orParam.push({ $like: `%${item}%` })
    })
    const shopResults = await shop.findAll({
      where: {
        name: {
          $or: orParam
        }
      }
    })
    if (!shopResults.length) {
      throw errorHelper(500, 'server error')
    }
    return shopResults
  }
}

module.exports = new ShopController()
